#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <sqlite3.h>
#import <UIKit/UIImageView.h>
#import <UIKit/UIApplication.h>
#import <SpringBoard/SBApplicationController.h>
#import <SpringBoard/SBApplication.h>
#import "../LockInfo/Plugin.h"

#import "FWCommon.h"
#import "FWTransToolbar.h"
#import "FWTableViewCell.h"
#import "FWToolbarViewCell.h"
#import "FWPlugin.h"
#import "FWListViewDelegate.h"
#import "FWListView.h"


@implementation FWPlugin

@synthesize items, plugin, lastUpdate, application, datasource, preferences, showToolbar;


// ******************************************************************************************
#pragma mark -
#pragma mark Initialisation and object management

- (id)initWithApplication:(FWApplication*)app
{
    if (!self.application)
        self.application = app;
    
    return self;
}

- (id)initWithPlugin:(LIPlugin*)pi
{
    FWApplication* app = [[[FWApplication alloc] init] autorelease];
    if (self = [self initWithApplication:app]) {
        NSLog(@"LI:FWTodo: Initialising plugin *************");
        
        self.application.plugin = self;
        self.plugin = pi;
        self.preferences = [[[FWPreferences alloc] initWithPreferences:pi.preferences] autorelease];
        self.lastUpdate = [NSDate dateWithTimeIntervalSinceReferenceDate:0];
        
        pi.tableViewDataSource = self;
        pi.tableViewDelegate = self;
        
        NSLog(@"LI:FWTodo: Initialised: %@", pi);
        DebugLog(@"LI:FWTodo: bundleIdentifier: %@", pi.bundleIdentifier);
        DebugLog(@"LI:FWTodo: bundle: %@", pi.bundle);
        DebugLog(@"LI:FWTodo: globalBundle: %@", pi.globalBundle);
        DebugLog(@"LI:FWTodo: preferences: %@", pi.preferences);
        DebugLog(@"LI:FWTodo: globalPreferences: %@", pi.globalPreferences);
        DebugLog(@"LI:FWTodo: managedBundles: %@", pi.managedBundles);
        
        NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
        
        [center addObserver:self selector:@selector(update:) name:LITimerNotification object:nil];
        [center addObserver:self selector:@selector(update:) name:LIViewReadyNotification object:nil];
        
        //[center addObserver:self selector:@selector(update:) name:[@"pocketinformant" stringByAppendingString:LIPrefsUpdatedNotification] object:nil];
        //[center addObserver:self selector:@selector(update:) name:[plugin.bundleIdentifier stringByAppendingString:LIPrefsUpdatedNotification] object:nil];
    }

    return self;
}

-(void)dealloc
{
    [items release];
    [plugin release];
    [application release];
    [datasource release];
    [preferences release];
    [toolbarView release];
    
    [super dealloc];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Attribute access

- (FWToolbarViewCell*)toolbarView
{
    return toolbarView;
}

- (void)setToolbarView:(FWToolbarViewCell*)value
{
    [toolbarView autorelease];
    toolbarView = value;
    [toolbarView retain];
}

- (void)setBadgeValue:(NSString*)value hidden:(BOOL)hidden
{
    [toolbarView setBadgeValue:value hidden:hidden];
}
    

// ******************************************************************************************
#pragma mark -
#pragma mark Table view counters

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{
    if (showToolbar) 
        return self.items.count + 1;
    else {
        self.toolbarView = nil;
        return self.items.count;
    }
}

- (NSInteger)tableView:(LITableView*)tableView numberOfItemsInSection:(NSInteger)section
{
    return self.items.count;
}

- (NSInteger)tableView:(LITableView*)tableView totalNumberOfItemsInSection:(NSInteger)section
{
    if ([datasource respondsToSelector:@selector(tableView:totalNumberOfItems:preferences:)])
        return [datasource tableView:tableView totalNumberOfItems:self.application preferences:self.preferences];
    else
        return self.items.count;
}


// ******************************************************************************************
#pragma mark -
#pragma mark Table view counters

- (UITableViewCell *)tableView:(LITableView *)tableView toolbarCellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *MyIdentifier = @"FWTodoTBar";
    static NSInteger kToolbarTag = 100;
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    if (cell == nil) {
        CGFloat height = [FWToolbarViewCell tableView:tableView heightForToolbarWithLabelStyle:tableView.theme];

        cell = [[[FWTableViewCell alloc] initWithFrame:CGRectMake(0, 0, 320, height) reuseIdentifier:MyIdentifier] autorelease];
        cell.backgroundColor = [UIColor clearColor];
        cell.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        cell.contentMode = UIViewContentModeRedraw;
        cell.autoresizesSubviews = YES;
        
        NSArray* navItems = [datasource application:self.application toolbarItemsForPrefs:preferences];

        FWToolbarViewCell* toolbar = [[[FWToolbarViewCell alloc] initWithFrame:CGRectMake(0, 0, 320, height)
                                                                         table:tableView 
                                                                  toolbarItems:navItems] autorelease];
        toolbar.tag = kToolbarTag;
        [cell.contentView addSubview:toolbar];
    }

    NSString* caption = @"";
    if ([datasource respondsToSelector:@selector(application:toolbarCaptionForPrefs:)])
        caption = [datasource application:application toolbarCaptionForPrefs:preferences];

    NSString* badge;
    if ([datasource respondsToSelector:@selector(application:toolbarBadgeForPrefs:)])
        badge = [datasource application:application toolbarBadgeForPrefs:preferences];
    
    // Record the toolbar so we can access it from the application
    FWToolbarViewCell* toolbar = [cell.contentView viewWithTag:kToolbarTag];
    self.toolbarView = toolbar;

    NSArray* toolbarItems = toolbar.items;
    BOOL updated = [datasource application:application configureToolbarItems:toolbarItems prefs:preferences];
    
    if (updated)
        [toolbar setItems:toolbarItems];

    // Update information
    [toolbar setInformationForTable:tableView indent:110 label:caption];
    [toolbar setBadgeValue:badge hidden:(badge == nil)];

    UIImage* subheaderImage = [tableView sectionSubheader];
    subheaderImage = [subheaderImage stretchableImageWithLeftCapWidth:0 topCapHeight:0];
    [toolbar setBackgroundWithImage:subheaderImage];
    
    [cell setNeedsLayout];
    
    return cell;
}


// ******************************************************************************************
#pragma mark -
#pragma mark Table header support

-(NSString*) tableView:(LITableView*) tableView detailForHeaderInSection:(NSInteger) section
{
    return [datasource tableView:tableView detailForHeaderInSection:section application:self.application preferences:self.preferences];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Table contents support

- (UITableViewCell *)tableView:(LITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSInteger row = indexPath.row;
    if (showToolbar) {
        if (row == 0)
            return [self tableView:tableView toolbarCellForRowAtIndexPath:indexPath];
        else
            --row;
    }
    
    static NSString *MyIdentifier = @"FWTodoCell";
    static int MyTag = 57;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, 320, 20) reuseIdentifier:MyIdentifier] autorelease];
        cell.backgroundColor = [UIColor clearColor];
        cell.contentMode = UIViewContentModeRedraw;
        cell.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        cell.autoresizesSubviews = YES;

        FWListView* lv = [datasource application:application cellViewForTableView:tableView preferences:preferences];
        lv.frame = cell.frame;
        lv.autoresizesSubviews = YES;
        
        lv.tag = MyTag;
        [cell.contentView addSubview:lv];
    }
    
    FWListView* view = (FWListView*)[cell.contentView viewWithTag:MyTag];
    
    NSDictionary* item = (NSDictionary*)[self.items objectAtIndex:row];
    [datasource tableView:tableView setDetailsUsingView:view forItem:item application:application preferences:preferences];

    return cell;
}

- (CGFloat)tableView:(LITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSInteger row = indexPath.row;
    if (showToolbar) {
        if (row == 0)
            return [FWToolbarViewCell tableView:tableView heightForToolbarWithLabelStyle:tableView.theme];
        else
            --row;
    }

    NSDictionary* item = (NSDictionary*)[self.items objectAtIndex:row];
    return [datasource tableView:tableView heightForItems:item application:self.application preferences:preferences];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Data reload support

- (void)tableView:(LITableView*)table reloadDataInSection:(NSInteger)section
{
    NSLog(@"LI:FWTodo: reloadDataInSection called");

    [self triggerUnconditionalRefresh];
}

- (void)triggerUnconditionalRefresh
{
    NSLog(@"LI:FWTodo: unconditionalRefresh triggered");

    self.lastUpdate = [NSDate dateWithTimeIntervalSinceReferenceDate:0];
    [self updateTasks];
}

- (void)triggerRedisplay
{
    NSLog(@"LI:FWTodo: Triggering redisplay");

    NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithCapacity:1];
    [dict setObject:items forKey:@"todos"];  
    [[NSNotificationCenter defaultCenter] postNotificationName:LIUpdateViewNotification object:self.plugin userInfo:dict];
}

- (void)update:(NSNotification*)notif
{
    if (!self.plugin.enabled)
        return;

    NSLog(@"LI:FWTodo: update triggered");
    
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    [self updateTasks];
    [pool release];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Table contents support

- (void)postUpdatedTodos:(NSArray*)todos
{
    [self performSelectorOnMainThread:@selector(setItems:) withObject:todos waitUntilDone:YES];
    self.lastUpdate = [NSDate date];
    
    NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithCapacity:1];
    [dict setObject:todos forKey:@"todos"];  
    [[NSNotificationCenter defaultCenter] postNotificationName:LIUpdateViewNotification object:self.plugin userInfo:dict];
}

- (void)updateTasks 
{
    DebugLog(@"LI:FWTodo: Updating tasks...");
    
    if (![application verifyApplication]) {
        NSLog(@"LI:FWTodo: Cannot find application!");

        showToolbar = NO;
        [self postUpdatedTodos:[NSArray array]];
    }
    else if (![application shouldUpdateForDate:self.lastUpdate] &&
             ![datasource application:self.application shouldUpdateForDate:self.lastUpdate]) {
        NSLog(@"LI:FWTodo: Update is not required");
    }
    else {
        DebugLog(@"LI:FWTodo: plugin prefs = %@", self.plugin.preferences);
        self.preferences = [[[FWPreferences alloc] initWithPreferences:self.plugin.preferences] autorelease];

        if ([self.application.applicationDelegate respondsToSelector:@selector(application:updateApplicationPrefs:pluginPrefs:)]) {
            NSDictionary* attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:application.preferencesPath error:NULL];
            NSDate* updated = [attrs objectForKey:NSFileModificationDate];
            
            if ([updated timeIntervalSinceReferenceDate] > [application.preferencesUpdated timeIntervalSinceReferenceDate]) {
                application.preferencesUpdated = updated;
                NSDictionary* applicationPrefs = [NSDictionary dictionaryWithContentsOfFile:[application preferencesPath]];
                [self.application.applicationDelegate application:application
                                           updateApplicationPrefs:applicationPrefs 
                                                      pluginPrefs:self.preferences];
                
                DebugLog(@"LI:FWTodo: Application prefs updated at %@ - read", updated);
                DebugLog(@"LI:FWTodo: Application prefs = %@", applicationPrefs);
            }
            else
                DebugLog(@"LI:FWTodo: Application preferences not updated since %@ - not read", updated);
        }

        if ([datasource respondsToSelector:@selector(application:isToolbarRequiredForPrefs:)])
            showToolbar = [datasource application:application isToolbarRequiredForPrefs:preferences];
        else
            showToolbar = NO;
        
        // Update data and read from database
        NSArray *todos = [datasource application:application fetchNewDataForPrefs:preferences];
        [self postUpdatedTodos:todos];
    }    
}


// ******************************************************************************************
#pragma mark -
#pragma mark Item preview

-(UIView*) tableView:(LITableView*) tableView previewWithFrame:(CGRect) rect forRowAtIndexPath:(NSIndexPath*) indexPath
{
    NSInteger row = indexPath.row;
    if (showToolbar) {
        if (row == 0)
            return nil;
        else
            --row;
    }

    BOOL allowPreviews = YES;
    
    if (row >= self.items.count || !allowPreviews)
        return nil;

    UIView* view = [datasource tableView:tableView previewWithFrame:rect atIndex:row forItems:self.items application:application preferences:self.preferences];
    return view;
}

@end
